package com.jgp.workflow.service;

import com.jgp.workflow.command.CommonJumpCmd;
import com.jgp.workflow.pojo.TargetPerson;
import com.jgp.workflow.pojo.TargetPersonType;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.impl.ServiceImpl;
import org.activiti.engine.impl.identity.Authentication;
import org.activiti.engine.impl.interceptor.CommandExecutor;
import org.activiti.engine.impl.persistence.entity.ExecutionEntity;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.task.Task;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 项目   jgp-cloud-parent
 * 作者   loufei
 * 时间   2020-07-21
 */
@Service
public class BackService {
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private HistoryService historyService;

    /**
     * 跳转节点并指定endTaskDefKey的待审批人为历史中最近一次endTaskDefKey节点的审批人
     * @param procId 流程实例ID
     * @param taskId 当前任务ID
     * @param endTaskDefKey 目标任务定义ID
     * @param msg 备注
     * @param operatorUser 操作人员ID
     */
    public void turnBackNew(String procId, String taskId, String endTaskDefKey, String msg, String operatorUser) {
        turnBackNew( procId,  taskId,  endTaskDefKey,  msg,  operatorUser,null);
    }
    
    /**
     * 跳转节点并指定endTaskDefKey节点的带审批人
     * @param procId 流程实例ID
     * @param taskId 当前任务ID
     * @param endTaskDefKey 目标任务定义ID
     * @param msg 备注
     * @param operatorUser 操作人员ID
     * @param targetPersons 目标任务待处理人员信息
     *                      {@link TargetPerson} new TargetPerson(TargetPersonType type, String targetId)
     *                      type: {@link TargetPersonType} TargetPersonType.USER 人员,TargetPersonType.ROLE 角色,TargetPersonType.ORG  部门
     *                      targetId: 如果TargetPersonType.USER 则为人的ID，如果TargetPersonType.ROLE 则为角色ID
     */
    public void turnBackNew(String procId, String taskId, String endTaskDefKey, String msg, String operatorUser, List<TargetPerson> targetPersons) {
        Map<String, Object> variables = new HashMap<>();
        taskService.addComment(taskId, procId, msg);
        Authentication.setAuthenticatedUserId(operatorUser);
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        ProcessDefinitionEntity processDefinition = (ProcessDefinitionEntity) repositoryService.getProcessDefinition(task.getProcessDefinitionId());
        ExecutionEntity execution = (ExecutionEntity) runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        ActivityImpl currentActivity = processDefinition.findActivity(execution.getActivityId());
        if(StringUtils.isBlank(endTaskDefKey)){
            HistoricTaskInstance lastTask = historyService.createHistoricTaskInstanceQuery().processInstanceId(procId).finished().orderByTaskCreateTime().desc().list().get(0);
            endTaskDefKey = lastTask.getTaskDefinitionKey();
        }
        ActivityImpl endActivity = processDefinition.findActivity(endTaskDefKey);
        CommonJumpCmd commonJumpCmd = new CommonJumpCmd(taskId, task.getExecutionId(), procId, endActivity, variables, currentActivity);
        CommandExecutor commandExecutor = ((ServiceImpl) repositoryService).getCommandExecutor();
        commandExecutor.execute(commonJumpCmd); //IdentityLinkType
        List<Task> activeTasks = taskService.createTaskQuery().processInstanceId(procId).active().list();
        for (Task activeTask : activeTasks) {
            if (CollectionUtils.isNotEmpty(targetPersons)) {
                targetPersons.forEach(targetPerson -> {
                    if (TargetPersonType.USER.equals(targetPerson.getType())) {
                        taskService.addCandidateUser(activeTask.getId(), targetPerson.getTargetId());
                    } else {
                        taskService.addCandidateGroup(activeTask.getId(), targetPerson.getType().name() + ":" + targetPerson.getTargetId());
                    }
                });
            } else {
                HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery().processInstanceId(procId).finished()
                        .taskDefinitionKey(activeTask.getTaskDefinitionKey())
                        .orderByTaskCreateTime().desc().list().get(0);
                taskService.addCandidateUser(activeTask.getId(), historicTaskInstance.getAssignee());
            }
        }
    }
    
}
